home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume25 / zip / part05 < prev    next >
Encoding:
Text File  |  1992-03-01  |  77.0 KB  |  2,036 lines

  1. Newsgroups: comp.sources.unix
  2. From: madler@cco.caltech.edu (Mark Adler)
  3. Subject: v25i146: zip - file compression/archive tool, Part05/07
  4. Sender: unix-sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: madler@cco.caltech.edu (Mark Adler)
  8. Posting-Number: Volume 25, Issue 146
  9. Archive-Name: zip/part05
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 5 (of 7)."
  18. # Contents:  history ship.c
  19. # Wrapped by vixie@cognition.pa.dec.com on Sun Mar  1 18:57:38 1992
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'history' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'history'\"
  23. else
  24. echo shar: Extracting \"'history'\" \(36825 characters\)
  25. sed "s/^X//" >'history' <<'END_OF_FILE'
  26. Note, this history contains mail addresses and ftp locations that no longer
  27. exist, such as addresses at wsmr-simtel20 and directory names containing
  28. w8sdz, among others.  For problems, the correct email address is
  29. zip-bugs@cs.ucla.edu.
  30. X
  31. X------------------------ Nov  7  1990   version 0.0 ------------------------
  32. X------------------------ Nov  8  1990   version 0.1 ------------------------
  33. X------------------------ Nov 12  1990   version 0.2 ------------------------
  34. X------------------------ Nov 14  1990   version 0.3 ------------------------
  35. Thank you for your comments.  Here is Zip 0.3 with almost all of that fixed.
  36. The changes include:
  37. X
  38. X1. Put \n\ for newlines in long strings (everyone had this problem).
  39. X2. Wrote my own bsearch (called search---different args).
  40. X3. Wrote my own timelocal (called invlocal), used whether STDC or not.
  41. X   (Note to Greg: look at the code---I found a simple way to do it.)
  42. X4. -m now deletes empty directories also.
  43. X5. Changed crc.c to util.c and put search() in util.c.
  44. X6. Changed "void *" to "voidp *" and made voidp void for STDC, else char.
  45. X7. Removed -a option.
  46. X8. Some minor changes to zip.doc.
  47. X
  48. I did not do anything about Cliff Manis's problem with DIR not being
  49. defined.  DIR should have been defined in sys/dir.h.  If it wasn't, then
  50. there's something wrong with dir.h, or it is missing, or the opendir, etc.
  51. functions are missing.  I don't really want to think about what to do for
  52. the latter possibility.
  53. X
  54. NUnzip 3.99 does not appear to be Unix-ready.  It fails for file names longer
  55. than 12 characters (Segmentation fault), cannot find explicit names that
  56. do not contain a dot, and does not notice the Unix identifier (which should
  57. switch off name to lower-case mapping).
  58. X
  59. X------------------------ Nov 20  1990   version 0.4 ------------------------
  60. Yo Zippers,
  61. X
  62. Here is a first attempt at a Zip intended to work on System V.  Try using
  63. X"make sysv" for such systems.  I also included replacements for memset()
  64. and memcmp() by Bill Davidsen and James Dugal for systems without those.
  65. Use "make old" to include those routines.  Sun's use getdents() like Sys V,
  66. even though it's BSD, so use "make sun".  For others, try just "make".
  67. X
  68. When using "make" a second time with a different request, it's best to erase
  69. all the .o files to force recompiling everything.
  70. X
  71. What follows are the changes I made and some things to try if you get it
  72. compiled.  Have fun.
  73. X
  74. Mark
  75. X
  76. X
  77. Changes from Zip 0.3 to Zip 0.4:
  78. X
  79. X1.  Changed third arg of search() to size_t to make lint happier.
  80. X2.  Replaced zip.doc with a man page, zip.1 (raw) and zip.man (formatted).
  81. X3.  rename() replaced with link() and unlink().
  82. X4.  Fixed vem in central header and added REVISION and REVDATE #define's
  83. X    to zip.h.  (Didn't read Phil's appnote.txt carefully enough there.)
  84. X5.  Removed prototypes except for development host (NeXT).  (They're only
  85. X    there for my benefit anyway---they should not affect the resulting
  86. X    code.  Consider them some meager documentation.)
  87. X6.  Changed rindex() to strrchr().
  88. X7.  Improved behavior on a write failure when -b is used.
  89. X8.  Added Bill Davidsen's and James Dugal's memset(), memcpy(), and
  90. X    memcmp() routines under the trusty ZMEM #define.
  91. X9.  Check that zip file is writeable before doing any real work.
  92. X10. Added #ifdef REGEX to use regcmp(), regex() instead of re_comp(),
  93. X    re_exec().  (We'll see if this works.)
  94. X11. Replaced opendir(), readdir(), closedir() with my own opend(), readd(),
  95. X    and closed() routines that use getdirentries() on BSD and getdents() on
  96. X    System V (I hope) and Sun's.  An #ifdef DIRENT selects getdents().
  97. X12. zip.h no longer #includes string.h, instead defining the string
  98. X    functions used explicitly.
  99. X
  100. X
  101. If you get Zip 0.4 to compile, here are some things to test:
  102. X
  103. X1.  Try zipping up some stuff, of course.  Use all the options that are
  104. X    implemented.  Especially try -rp and -rpm on a directory tree (use
  105. X    *test* files and directories, of course).
  106. X2.  Naturally check with unzip -t, but also check with "zip xxx" where
  107. X    xxx.zip is the zip file.  This should say "nothing to do", but if it
  108. X    says "error in zip file structure", there's a problem.
  109. X3.  After zipping, check that there are no $Z* files leftover.
  110. X4.  Try using -b, specifying a path on another device.  Check for $Z*'s.
  111. X5.  Try -d and a regular expression (like \*.o) on a zip file.
  112. X6.  And I'm interested in timing---try it on a 500K or so text file.
  113. X
  114. X------------------------ Nov 27  1990   version 0.5 ------------------------
  115. Hail fellow zippers,
  116. X
  117. Here's Zip 0.5.  The biggie is it now includes implosion, courtesy of Rich
  118. Wales.  Even as we speak, he is working on new algorithms for implode that
  119. promise to be significantly faster.  He might even get a paper out of it ...
  120. X
  121. You can use the -s option (shrink only) when testing to save a little time,
  122. but also try it normally to test implosion (if you test with text files
  123. of reasonable length, implosion will be chosen for most of them).  Also, for
  124. speed testing of implosion, use -i to not waste time trying to shrink.
  125. X
  126. Including implosion about doubles the size of zipnn.tar.Z, so I would like
  127. some input on distributing subsequent versions.  Would y'all like to keep
  128. on getting the uuencoded version via mail, or would you prefer a notice
  129. about availability via anonymous ftp on simtel20.army.mil in <w8sdz.zip>?
  130. X(I have been sending the previous versions to Keith to put there, and will
  131. continue to do so.  I do not know what the lag time is for him to move it
  132. there.)
  133. X
  134. The other important change is that this is another attempt at getting the
  135. directory access routines working on all systems.  Read the installation
  136. part of the manual page (zip.man).  And if you feel like, read the whole
  137. thing.  I'm also taking suggestions for and bugs in the documentation.
  138. X
  139. The differences from Zip 0.4 include:
  140. X
  141. X1. Changed all occurences of "size_t" to "extent" and typedef'ed extent
  142. X   to size_t (after an #include <stddef.h>) for ANSI C, or unsigned int
  143. X   otherwise.  If anyone finds that they have a non ANSI C, that size_t
  144. X   is defined, and that it is not the size of the compiler's int, then
  145. X   please let me know.
  146. X2. Changed help() to put the help text in a static array of strings and
  147. X   then printf() for each line.  Some compilers barfed on the long
  148. X   string.  Suggested by davidsen@crdos1.crd.ge.com.
  149. X3. Added Rich Wales' implode routines, made their inclusion the default
  150. X   (changed #ifdef IMPLODE to #ifndef NOIMPLODE).
  151. X4. Put "extern int errno;" in unixfile.c (redundant extern's should be ok).
  152. X5. Minor changes to the man page (zip.1 and zip.man).
  153. X6. Added warnings for names given on the command line that are not matched.
  154. X   Lack pointed out by grimesg@sj.ATE.SLB.COM (George).
  155. X7. Changed back to opendir(), etc. on BSD systems.
  156. X8. Added NDIR #define for HPUX to #include <ndir.h> instead of <sys/dir.h>.
  157. X9. Redid Makefile, adding next (use shared library), sysvpw (System V's
  158. X   that require linking the libPW library for regex routines), and hpux
  159. X   (see #8 above).
  160. X
  161. As usual, report problems to info-zip@wsmr-simtel20.army.mil.  If you wish,
  162. you can, in addition, send the same report to me (madler@piglet.caltech.edu)
  163. or Rich (wales@cs.ucla.edu) if the problem is with implosion (i* files) for
  164. quicker reponse.
  165. X
  166. your humble servant,
  167. Mark Adler
  168. X------------------------ Dec  7  1990   version 0.6 ------------------------
  169. Greetings and Felicitations Honorable Zip Compatriots,
  170. X
  171. I have uploaded Zip 0.6, which incorporates most of your helpful comments,
  172. to Simtel20.Army.Mil, and it should evenually end up in <W8SDZ.ZIP> as
  173. ZIP06.TAR-Z.  The most significant change is the addition of encryption
  174. both as the -e option in Zip, and a new program, ZipCloak, that encrypts
  175. and decrypts zip entries.  This surely adds some new portability problems,
  176. due to the getp() routine which reads a password from the terminal with no
  177. echoing.  We'll see how well this flies ...
  178. X
  179. If someone wants to PKZIP up the tar.Z file, please do so.  I didn't zip
  180. it up myself because a) I'm lazy, and b) PKZIP can compress it better
  181. anyhow, and I don't have a PC.
  182. X
  183. Also, there is an EXPORT symbol used to remove encryption, so I can make
  184. an export version that does not have -e or ZipCloak.  This version will
  185. simply be missing a few source files and have a different Makefile.
  186. X
  187. I also added a few systems to the Makefile, and made some other changes to
  188. it based on all your detailed comments.  If it still works after all that,
  189. I'll be amazed.
  190. X
  191. Those and other changes from 0.5 to 0.6 are detailed at the end of this note.
  192. X
  193. I have not addressed the portability problem with the implode routines,
  194. since that is Rich's domain.  I have no idea what is causing it.  (For those
  195. who don't know, one system produced remarkable 90% compression rates with
  196. implode, but alas, it is a bug.)
  197. X
  198. One fellow complained that zipping up the README file results in a zip file
  199. that is larger than the original, even though Zip claims it compressed it.
  200. Well, it did compress it, but the ZIP file format has an overhead of
  201. X76+2*N bytes per file+22 bytes, where N is the length of the file name.
  202. And that's without comments or "extra" information.  So, a zip file with a
  203. single file whose name has six characters has an overhead of 110 bytes.
  204. README gets shrunk by 16% from 274 bytes to 230 bytes, resulting in a total
  205. zip file size of 340 bytes---larger than the original file (274 bytes).
  206. The moral is don't expect zip to compress a single small file.  The other
  207. moral is use unzip -v to see the compression.
  208. X
  209. Someone else asked about multi-disk zip files.  I'm not sure I believe in
  210. those, since PKZIP and PKUNZIP do not appear to suppport them (though it is
  211. part of the ZIP file definition in APPNOTE.TXT).  What I was planning on
  212. doing for that case was to write a ZipSplit program that would take a large
  213. zip file and try to optimally split it into the fewest number of zip files
  214. that are all less than the specified size.  Each would be a complete, stand
  215. alone zip file---not part of a single, multi-disk zip file.  There would
  216. also be a ZipMerge program.
  217. X
  218. This is the version of Zip that will live in infamy (note the revision date).
  219. Of course, some current Presidents of the United States think that should be
  220. September 7th, but I won't name any names.
  221. X
  222. I am going on vacation for about two weeks, so I expect to find many new
  223. problems reported upon my return.
  224. X
  225. And lastly, for my Holiday Greetings: Party On Dudes.
  226. X
  227. Mark Adler
  228. madler@piglet.caltech.edu
  229. X
  230. X
  231. Here are the changes from Zip 0.5 to Zip 0.6:
  232. X
  233. X1.  Minor documentation changes (zip.1 and zip.man).
  234. X2.  Fixed an embarrasing lack of recursion in opend/readd/closed functions
  235. X    that only existed in 0.5.
  236. X3.  Moved $(LDFLAGS) to end of the linking command line in Makefile.
  237. X4.  Added make dnix for DNIX 5.2, 5.3 not using optimization (no -O).
  238. X5.  Wrote ZipCloak for encryption and decryption.
  239. X6.  Rich changed the output routines of implode to use zfwrite and zputc to
  240. X    provide hooks for encryption (defined in crypt.h).  Also removed
  241. X    function prototypes unless PROTO defined.
  242. X7.  Added encryption (-e) to Zip.
  243. X8.  Added make pyramid (use rindex() instead of strrchr()).
  244. X9.  Changed make to $(MAKE) and cc to $(CC) in Makefile.
  245. X10. Took out strip in Makefile.
  246. X11. Changed year from 1991 to 1990.  (How'd *that* get in there?  Of course,
  247. X    it's not as bad as when I wrote a check the other day and dated it 1977.
  248. X    I think my brain cell isn't working as well as it used to.)
  249. X12. Added make cray (use scc instead of cc).
  250. X13. Added make amdahl (use system() instead of rmdir()).
  251. X14. Added entry of one-line comments for added files (-c).
  252. X15. Put comment delimiters around name following #endif's in Rich's code.
  253. X
  254. X------------------------ Feb 13  1991   version 0.7 ------------------------
  255. XFellow stuck zippers,
  256. X
  257. Well folks, it's been a while since 0.6. so there have been a lot of
  258. changes on the way to 0.7.  The exhaustive listing is below, but here are
  259. some highlights ...
  260. X
  261. Implode now (appears) to be PKUNZIP compatible.  There were many odd
  262. little requirements implosed by the coding of PKUNZIP that were obtained
  263. from Phil Katz and associates.  Now that Rich has that working, he will
  264. likely be working on much faster string matching routines to speed up
  265. implode.
  266. X
  267. User interrupts (control-C or kill) are now caught and the temporary files
  268. are deleted, making for a clean getaway.
  269. X
  270. Self-extracting zip files for MSDOS can now be processed, with the
  271. extensions zip, ZIP, exe, or EXE.  This allows you to make self-extracting
  272. zip files for MSDOS by taking an existing one (like PKZ110.EXE) and
  273. deleting all the entries to get a prototype self-extracting zip file that
  274. can be copied and added to.  Of course, you should only do this if you are
  275. a registered user of PKZIP.  Note that if the file does not end in .zip,
  276. you have to give the full name.
  277. X
  278. I have relaxed some of the restrictions on zip files to allow processing
  279. ones with "authenticity verification" (applied by the PUTAV program that
  280. comes with PKZIP).  Of course, the authenticity no longer checks out if
  281. you muck with the file, but at least you can muck with it now.
  282. X
  283. The Makefile has been considerably simplified, thanks to suggestions from
  284. Jean-Loup Gailly.  Also, I wrote my own sh expression matcher, eliminating
  285. the regular expression hassles, and the REGEX symbol and -lPW options in
  286. the Makefile.
  287. X
  288. Many, many cosmetic changes, the most dangerous of which was turning on
  289. prototypes again in the hopes we can get them to work.  If they cause you
  290. problems, record the problems (for me), and then add a -DNOPROTO to the
  291. appropriate line in the Makefile and try again.
  292. X
  293. This version now compiles under Microsoft C 5.1 and Turbo C++ 1.0, with
  294. much thanks to Jean-Loup Gailly.  I say "compiles" and not "works" because
  295. I have not thoroughly tested it.  It does work, but there may be errors in
  296. the port as well as errors in the design.  By the latter I mean that there
  297. may be some disagreement over what you expect it to do and what it does,
  298. especially with regards to upper and lower case names and wildcard
  299. patterns.  Also, the implode routines do not yet work under MSDOS, so the
  300. compilations are done using NOIMPLODE.  There are two dumb batch files to
  301. do the compile: doturboc.bat and domsc.bat.  If someone would like to
  302. write make files for the make utilities that come with those languages,
  303. please be my guest.  I'm just too lazy.  However, I would probably resist
  304. including make files that require a make utility that does not come with
  305. those languages, be it commercial, shareware, or free.
  306. X
  307. There are two new programs: ZipSplit and Ship.  ZipSplit tries to split a
  308. big zip file into the smallest number of zip files less than a specified
  309. size.  This is to aid in using zip to backup to floppies.  It has the
  310. limitation that it cannot break up an entry in a zip file, since it makes
  311. complete, standalone zip files.  This means if any entry is larger than
  312. the specified size (plus some overhead), zipsplit will give up and not do
  313. the split.  It does *not* implement the multi-disk zip file format implied
  314. in APPNOTE.TXT.  ZipSplit will optionally write an index file and deduct
  315. the size of that file from the first zip file so both will fit on the
  316. first disk.
  317. X
  318. Ship is a fixed-up version of a program I have been using myself for some
  319. time in place of uuencode/uudecode.  It's purpose is to facilitate sending
  320. zip files through the mail.  It uses a more efficient coding scheme than
  321. uuencode (four bytes per five characters instead of three bytes per four
  322. characters) and includes a crc at the end of each file to check the
  323. veracity what was received.  It can split its output to a specified size
  324. and recombine it automatically at the other end, verifying the sequence.
  325. It can also mail the parts to a specified address, with subject lines
  326. identifying the parts, instead of making a bunch of files that you're just
  327. going to mail and delete anyway.  Example:
  328. X
  329. X     % ship -500 -m saddam@pickle.iq README zip07.zip
  330. X     README shipped
  331. X     zip07.zip shipped
  332. X     files part0001..part0004 mailed
  333. X
  334. will mail README and zip07.zip together in four chunks of 500 or fewer
  335. lines each.  At the other end, Saddam can save the parts into the files
  336. named in the subject lines (part0001..part0004), and then do:
  337. X
  338. X     % ship -u part*
  339. X     README received
  340. X     zip07.zip received
  341. X
  342. XFor now, zip.1 (and zip.doc) are incomplete as far as MSDOS goes.  I'll
  343. put off doing that until the MSDOS version has stabilized.  Likewise, I
  344. have put off writing zipcloak.1, zipsplit.1, and ship.1 for the same
  345. reason.
  346. X
  347. There are, of course, all the little changes that fix bugs (what are
  348. those?), make the Makefile work on more systems, documentation, and,
  349. for the alert reader, an undocumented option ...
  350. X
  351. As usual, send reports to info-zip@wsmr-simtel20.army.mil, so everyone
  352. can get a chuckle out of whatever new bugs I've introduced.
  353. X
  354. Mark Adler
  355. madler@pooh.caltech.edu
  356. X
  357. X
  358. Changes from release 0.6 to release 0.7:
  359. X
  360. X1.  Changed Makefile to use mv instead of -o on compiles.
  361. X2.  Added MAKE = make to Makefile.
  362. X3.  Catch user interrupt or termination and delete temporary files.
  363. X4.  Allow general purpose flags in local and central headers to differ in
  364. X    the "reserved" bits.  Keep both for copying zip entries verbatim.
  365. X5.  Removed prototype for closedir--return value not used and inconsistent
  366. X    across systems.
  367. X6.  Wrote ZipSplit to break a large zip file into the smallest number of
  368. X    zip files less than a specified size.  Run zipsplit with no arguments
  369. X    to see the command help.
  370. X7.  Put error messages in globals.c to be common across zip, zipcloak, and
  371. X    zipsplit.  Use #define's in zip.h for error numbers.
  372. X8.  Changed getp() to open a new file for the terminal device, and added
  373. X    the echon() function to turn echoing back on when interrupted at
  374. X    password prompt.
  375. X9.  Added warn()'s to distinguish various zip file structure errors.
  376. X10. Allow "extra" fields in local and central headers to differ.
  377. X11. Fixed percent compression calculation to work for very large files.
  378. X12. Included the program (makecrc.c) that generates the CRC table.
  379. X    makecrc.c is not compiled or run by the Makefile, but is present for
  380. X    completeness.
  381. X13. Added an undocumented (except for here) option, -v, to zip that checks
  382. X    for "oddities" in the zip file structure and points them out if found
  383. X    (but continues processing).
  384. X14. Put prototypes in crypt.h inside #ifdef NeXT to avoid redefinition
  385. X    problems with other compilers.
  386. X15. Added "make zilog" for Zilog S8000 running Zeus 3.21.
  387. X16. Minor changes to the manual page (zip.1 and zip.doc).
  388. X17. Fixed bug in replace() (manifested by -b option).
  389. X18. readzipfile() now also checks the central directory start and size in
  390. X    the end of central directory header.
  391. X19. Allow modification of self-extracting zip files (exe instead of zip).
  392. X20. Allow .ZIP as valid suffix as well as .zip (also .EXE and .exe).
  393. X21. Cleaned up malloc usage, free'd everything malloc'ed.
  394. X22. fclose'd all fopen'ed files explicitly.
  395. X23. Corrected assignment of one ftell() result from an int to a long.
  396. X24. Considerably simplified Makefile, based on Jean-Loup Gailly's
  397. X    suggestions.
  398. X25. Renamed unixfile.c to fileio.c in anticipation of non-unix support.
  399. X26. Removed const's (pesky little buggers caused too many problems).
  400. X27. Wrote my own shell expression compare routine, took REGEX and -lPW's
  401. X    out of Makefile, which removed the sysvpw make option.
  402. X28. Added tempname() prototype to crypt.h for the implode routines to use.
  403. X29. Trying string.h for prototypes of string functions if __STDC__
  404. X    defined, which is what unzip.h does.
  405. X30. Turned prototypes on if __STDC__ defined (we'll try this one more
  406. X    time).  They can be turned off using NOPROTO.
  407. X31. Improved source documentation.
  408. X32. Changed prototype of open in fileio.c to OF((char *, int, ...)).
  409. X33. Removed "local" from prototypes of main() (after all, it's *not*
  410. X    local).
  411. X34. Wrote Ship program to supplant uuencode--slightly more efficient, has
  412. X    error checking, file splitting, automatic mailing, other features.
  413. X    Ship currently uses the command:
  414. X        /usr/ucb/mail -s subject < tempfile
  415. X    to send mail.  Please let me know what works for your system.  Note
  416. X    that I want to be able to specify a subject line.
  417. X35. Ported to MSDOS Microsoft C 5.1, based on Jean-Loup Gailly's work.
  418. X36. Fixed add/update bug when -p not used.
  419. X37. Handle lower case conversion and devices (e.g. C:) for MSDOS.
  420. X38. Indented the #ifdef/#ifndef constructs that do not contain function
  421. X    definitions, to improve the readability somewhat.
  422. X39. Cleaned up error handling.  Now use perror() for i/o errors.  Put the
  423. X    errors and messages in ziperr.h.
  424. X40. Ported to MSDOS Turbo C++ 1.0.
  425. X41. Implemented wild card expansion on the command line for MSDOS and
  426. X    handle MSDOS matching (*.* == all, not *).
  427. X42. Changed version required to unzip to 11 (1.10) since the implode
  428. X    routines can procude an overlapping match one away from the end of the
  429. X    window (PKUNZIP 1.00 requires two away from the end).
  430. X43. Changed old next make option to next10 (for version 1.0) and added a
  431. X    new next make option for 2.0 (just called next) that uses the -object
  432. X    linking option for smaller executables.
  433. X44. Added -z option to take a multi-line zip file comment from stdin.
  434. X45. Changed temporary names from $ZXXXXXX to _ZXXXXXX, where XXXXXX is
  435. X    filled in by mktemp().  This avoids problems with "rm $Z*" in sh.
  436. X46. Got new implode routines from Rich that are (hopefully) PKUNZIP
  437. X    compatible.
  438. X47. When -b is not specified, put the temporary files in the same
  439. X    directory (i.e. the same device) that the zip file is (or will be) in.
  440. X48. Added doturboc.bat and domsc.bat files to compile for Turbo C++ 1.0
  441. X    and Microsoft C 5.1.  I am interested in successes and failures with
  442. X    other versions of those compilers.  In this version, the implode
  443. X    routines do not work under MSDOS.
  444. X------------------------ May  6  1991   version 0.8 ------------------------
  445. Buenos Dias Amigos,
  446. X
  447. Heer ees dee Cinco de Mayo reeleese of seep, aka Zip 0.8.  The changes
  448. from 0.7 are in the (long) list below, but here are some highlights:
  449. faster implode, faster shrink, first attempt at a VMS version (thanks
  450. to Cave Newt), and a new program, ZipNote, to aid in editing zip file
  451. comments.  To compile under VMS, do an "@makevms.com".  To compile using
  452. Mircosoft C do a "make makefile.msc".  To compile using Borland (Turbo)
  453. C, do a "make -fmakefile.bor".  Please try to break any or all of these
  454. programs in every conceivable way--we're getting close a public release.
  455. Thank yew fer your support.
  456. X
  457. Mark Adler
  458. madler@pooh.caltech.edu
  459. X
  460. Changes from 0.7 to 0.8:
  461. X
  462. X1.  Added the -n option to prevent compressing already compressed files.
  463. X    Documented -n in zip.1.
  464. X2.  Check the length of the compressed data in zipup() in case implode or
  465. X    shrink has a bug.
  466. X3.  Fixed -v option to not complain about needing PKUNZIP 1.1.
  467. X4.  Added report of store/shrink/implode sizes when -v (verbose) used.
  468. X5.  Put in Rich's patch to fix 100% implosion bug.
  469. X6.  Fixed -i bug.
  470. X7.  Made changes to im_ctree.c and implode.c to (hopefully) make it work
  471. X    under MSDOS.  (Jean-Loup said declare topmaxvals and botmaxvals as
  472. X    U_INT in im_ctree.c, and use MSDOS, not __MSDOS__ in implode.c.)
  473. X8   Added implode routine compilation to domsc.bat and doturboc.bat.
  474. X9.  Replaced FILENAME_MAX with FNMAX, which is now always 1024.  (It seems
  475. X    FILENAME_MAX is incorrectly set to 14 on some System V Unixii.)
  476. X10. Changed BEST to -1 so it is different from STORE (=0).  Redid some of
  477. X    the method logic in zipup().
  478. X11. Changed wb+ to w+b in implode.c.
  479. X12. Removed "nothing to do" error for -u and -f.
  480. X13. Zip source distributions will now have tabs removed, except for
  481. X    Makefile and Makefile.exp (no feelthy tabs rule).
  482. X14. Changed zip error on open failure to a warning.  This accounts for
  483. X    files that do not have read permission or are locked, and files
  484. X    deleted during the zip.  For entries being updated, the old entry is
  485. X    copied over instead.  This change had the side effect of removing the
  486. X    zipskip() routine.
  487. X15. Removed OBJC dependencies in Makefile.exp (didn't belong).
  488. X16. Removed strip from Makefile, instead using the -s link option.
  489. X17. Fixed -um and -fm to delete files whose entry's times were checked in
  490. X    the archive.
  491. X18. Put portability stuff common to zip.h and crypt.h into tailor.h.
  492. X19. Added mark tracing to -v (for debugging).
  493. X20. Changed name and zname logic--an external name is always converted
  494. X    into an internal zname, and vice-versa.  zname is now always
  495. X    malloc'ed.
  496. X21. Fixed -z to use CRLF between lines (for PKZIP) and have no newline
  497. X    after the last (or only) line.
  498. X22. Added clean to Makefile (deletes *.o, zip, zipcloak, zipsplit, ship).
  499. X23. Replaced LDFLAGS with LFLAGS1 and LFLAGS2 in Makefile (splits link
  500. X    options before and after object files as in unzip).
  501. X24. Added scodos to Makefile (from Bill Davidsen).
  502. X25. Included stdio.h in tailor.h--removed stdio.h from zip.h and
  503. X    implode.h.
  504. X26. Do not include stddef.h if M_XENIX defined.
  505. X27. Cast the arguments of all free() calls to (voidp *).
  506. X28. Added casts to char * for memset() and qsort() args in zipsplit.c.
  507. X29. Changed implode.h to define malloc and str* properly.
  508. X30. Fixed invlocal() to handle integer overflow correctly, as well as
  509. X    reliably across compilers.
  510. X31. Got new implode.h from Rich with fix #29 above.  Removed stdio.h
  511. X    include.
  512. X32. Commented out the abort() calls in im_ctree.c.
  513. X33. -ee requests a verification of the encryption password.
  514. X34. malloc and free tempath.
  515. X35. Documented -, SCO, and scodos in zip.1, and - in help().
  516. X36. Added revision.h for Zip revision number and date.
  517. X37. -u and -f with no arguments now (both) freshen the entire archive.
  518. X38. Use /Oait instead of /Ox for MSC to avoid loop optimization (buggy on
  519. X    5.1, and sometimes even crashes compiler!).
  520. X39. Added ! (reverse) range matching to shmatch(), and early abort on '*'
  521. X    failures (speeds up pathological patterns).  Cleaned up '\' (escape)
  522. X    handling.
  523. X40. Changed '!' in ship to '{' (some EBCDIC translations do not include
  524. X    !).  However, unship (ship -u) still understands '!'.  Also added the
  525. X    -v option of ship to print out the version and revision date.  Also
  526. X    now refuse to overwrite an existing file when unshipping (ship -u),
  527. X    but there is a -o option to overwrite anyway.
  528. X41. Added a "fast" mode to ship using hard-arithmetic coding that is
  529. X    nearly as efficient as base 85 coding, but much faster on 16-bit
  530. X    machines (base 85 coding uses 32 bit multiplication and division).
  531. X42. Put tailor.h back in ship.c, so that ship.c can stand on its own.
  532. X43. Made -p the default, and added a new option, -j to do the opposite
  533. X    (junk directory names).  -p is still there but does nothing, so as to
  534. X    avoid annoying PKZIP users.  Changed documentation and help()
  535. X    accordingly.
  536. X44. If -j is used, and two files are to be added with the same name, then
  537. X    zip exits with an error.
  538. X45. Wrote ZipNote for editing zipfile comments.  Just do zipnote for
  539. X    usage.
  540. X46. Replaced Rich's im_lmat.c with a new one from Jean-Loup.  Improves the
  541. X    speed of implode by a factor of two, and even more for very large
  542. X    files.
  543. X47. Reduced the execution time of shrink by 33% simply by moving the code
  544. X    around (eliminated some unnecessary calls, moved some tests).
  545. X    Shrink's execution time is now about 50% more than compress (it used
  546. X    to take over twice as long).  Hash tables for shrink are still
  547. X    intended for a future release.
  548. X48. VMS mods from Greg: replace() unlinks only after copy, changed
  549. X    delete() to destroy(), added code for deletedir(), use creation time
  550. X    instead of modification time, warn if stamp() attempted, changed
  551. X    includes, make link rename and unlink delete, added findfirst,
  552. X    findnext stuff, added wild() for VMS, modified newname(), procname().
  553. X49. Implemented internal<-->external name conversions for MSDOS and VMS.
  554. X50. For VMS matching, changed ? to %, removed bracketed ranges.
  555. X51. Added makevms.com, stolen from Unzip (vms_make.com).
  556. X52. Implemented -k (force the zip file to look like it was made by PKZIP).
  557. X53. Removed implode for VMS (it crashes--haven't tracked down where).
  558. X54. Got Jean-Loup's makefile.dos working for MSC 5.1 (makefile.msc) and
  559. X    Turbo C++ 1.0 (makefile.bor).
  560. X------------------------ Jul 11  1991   version 0.9 ------------------------
  561. Hey gang,
  562. X
  563. Here is our very-nearly-ready-to-release version of Zip.  There will be no
  564. features added or changed from 0.9 to 1.0--only bugs fixed.  I hope that
  565. we can get 1.0 out pretty quickly then.  This is really your last chance to
  566. find bugs before it goes out, so please, please test all the programs as
  567. much as you can.  Try all the features, if possible, and perhaps try to
  568. think of ways to break the programs.  Also, and this is very important, read
  569. the documentation in zip.doc and "debug" that too.  I already know that it
  570. is not complete in 0.9, but please send any comments about errors, omissions,
  571. format, or whatever to Info-ZIP, even if they seem obvious.
  572. X
  573. The highlights of the changes from 0.8 to 0.9 are: faster, slicker implode;
  574. operation in small model on MSDOS for speed; a new temporary file interface
  575. for faster operation on small files; some shrink improvements; and some new
  576. options (-y, -g, -q).  Also, ship has been enhanced in several ways, not the
  577. least of which is a help option (-h).
  578. X
  579. Have fun.
  580. X
  581. Mark Adler
  582. madler@tybalt.caltech.edu
  583. X
  584. X
  585. Changes from 0.8 to 0.9:
  586. X
  587. X1.  Removed the "not implemented yet" note in help() for -k (it *is*
  588. X    implemented now).  Removed from bug list in zip.1 too.
  589. X2.  Fixed Turbo C implode bug.
  590. X3.  Added /link /e in makefile.msc for ship.c.
  591. X4.  Made handler() in zipnote.c the same as handler() in zipsplit.c.
  592. X5.  Added -y option in Unix to store symbolic links as such.  (We need
  593. X    Unzip to be aware of symbolic links and use symlink() to recreate them.)
  594. X6.  Ignore control characters in unship input.
  595. X7.  Use prototypes and ANSI libraries if MSDOS.  (Used to check for Turbo C,
  596. X    but Microsoft C 6.0 also does not define __STDC__ unless strict ANSI
  597. X    is requested.)
  598. X8.  Added mod to ct_fsort() from Rich that should remove any qsort()
  599. X    dependencies in implode output.
  600. X9.  Removed some 32/16-bit prejudices in util.c and crypt.c that affect
  601. X    64-bit integer (short, int, and long) machines (Cray).
  602. X10. Added System V MAILX option to ship.c to use the mailx command.  This
  603. X    is automatically activated by DIRENT if ship is compiled by the zip
  604. X    makefile.
  605. X11. Added patches from Greg Roelofs for echo control on Cray and Amdahl.
  606. X    The patch uses termio.h and ioctl(), and is assumed for all System V,
  607. X    not just those (we'll see how this flies).
  608. X12. Changed -Ox to -Oacegit -FPi87 in makefile.msc.  Added /nologo to link.
  609. X13. Applied J-L's 082 mods (Sinatra style): select 4K window for < 5.5K,
  610. X    8K window for >= 5.5K files (just like PK does); various im_ctree.c
  611. X    mods verbatim (except for the treename warning, which I did differently);
  612. X    various im_lmat.c mods verbatim (except macros are done the ugly portable
  613. X    way); farmalloc'ed in shrink.c; changed makefile.msc and makefile.bor to
  614. X    use small model; added J-L to zip.1 acknowledgements (oops).
  615. X14. Moved struct zlist's and struct flist's to far storage (needed by above
  616. X    mods).  Unfortunately, I can't move the names and other things pointed to
  617. X    by those structures into the far space, since they are arguments to
  618. X    library functions like strcmp() and fwrite().
  619. X15. Changed zipup() to both shrink and implode only on files smaller than
  620. X    BSZ.  Also in that case, free up shrink data structures before allocating
  621. X    the implode data structures.  Changed from fopen() to open() except for
  622. X    VMS.
  623. X16. Fixed bug in dosmatch() to free malloc'ed space.
  624. X17. MINIX mods (do not need minix make option): call tempname() with a unique
  625. X    character (MINIX mktemp() flawed); defined S_IWRITE as S_IWUSR if S_IWUSR
  626. X    defined; removed explicit signal dereference.
  627. X18. Fixed bug in unship when used as a filter with no args.
  628. X19. Changed getnam() to not use static storage.
  629. X20. Copy permissions from old to new zip file (zip, zipcloak, zipnote).
  630. X21. Added patches for AT&T 3B1, added 3b1 target to makefile, added to zip.1.
  631. X22. Made FNMAX 256 for MSDOS (is 1024 otherwise).
  632. X23. Used the "pyr" predefined symbol for Pyramid systems in tailor.h.
  633. X24. Added Greg's VMS mods to ship.c.  Added help to ship.c (-h or -?).
  634. X    Changed meaning of -nnn arg from lines to K.
  635. X25. Moved ZMEM routines to fileio.c to properly include them in zipnote and
  636. X    zipsplit.
  637. X26. Added -s option to ship to specify a subject line prefix.
  638. X27. Fixed -z in zip to not trash leading blank lines in the comment.
  639. X28. Made ship recognize "unship" in argv[0] a little more flexibly.
  640. X29. Made sure temporary zip files are closed before being deleted by an
  641. X    error or interrupt.
  642. X30. Added a new temporary file interface and new source files tempf.c and
  643. X    tempf.h.  This avoids making temporary files for small (<16k) output.
  644. X    Both shrink and implode use this.
  645. X31. Added OS/2 patches, files.  However, left zip case-sensitive for OS/2
  646. X    names, as in Unix.
  647. X32. Removed amdahl target in makefile, using UTS symbol instead.
  648. X33. Changed -y to depend on definition of S_IFLNK.
  649. X34. Avoid leading periods on lines in ship output by inserting a space.
  650. X35. Ship is now extensible: added a warning for "unsupported keyword".
  651. X    Such keywords can appear before the "ship" line, for example.
  652. X36. Added -g option to allow "growing" the zip file.  If just adding new
  653. X    entries to a zip file, -g will write over the old zip file without
  654. X    creating a temporary.  The danger is that if there is an error, the
  655. X    old zip file will be lost.  If not just adding, then -g is ignored.
  656. X37. Added aux (A/UX) target to makefile.
  657. X38. In shrink.c, removed unnecessary FreeList and ClearList arrays, and
  658. X    the recursive Prune() routine.  This also resulted in a speedup in
  659. X    shrink of about 15%.  It is now only about 30% slower than Unix compress.
  660. X39. Added -q option for quiet operation.
  661. X------------------------ Sep 21  1991   version 1.0 ------------------------
  662. Hello world!
  663. X
  664. This is the first public release version of Zip and its cohort utilities.
  665. We hope you enjoy using it much much more than we enjoyed writing it and
  666. trying to get it to work on every fritzing raffing bliffing nobbin Unix
  667. system in the galaxy.
  668. X
  669. Please feel free to send any problems, complaints, suggestions, kudos,
  670. ridicule, or whatever to zip-bugs@cs.ucla.edu.  If there were a way to
  671. send cookies over the net, we'd accept those too.
  672. X
  673. Thank yew fer yur support.
  674. X
  675. Mark Adler
  676. madler@tybalt.caltech.edu
  677. X
  678. X
  679. Changes from 0.9 to 1.0:
  680. X
  681. X1.  Removed some pesky carriage returns masquerading as spaces in fileio.c
  682. X    and zipup.c.
  683. X2.  Removed #include memory.h in tempf.c (string.h good enough).
  684. X3.  Compile ship in doturboc.bat.
  685. X4.  Miscellaneous zip.1 (zip.doc) changes.
  686. X5.  Fixed mistake in stamp() in fileio.c (didn't double seconds).
  687. X6.  Applied Jean-Loup's mods for Cray's (do not assume 16-bit shorts).
  688. X7.  Removed pyramid make option, since #ifdef pyr seems to work.
  689. X8.  Added some casts to tempf.c to clean up some warnings.
  690. X9.  Added comment to makefile.exp saying what it is.
  691. X10. Removed length checks in zipup.c to fix problem with using Vax variable
  692. X    record length formats.
  693. X11. Fixed VMS replace-across-devices problem.
  694. X12. Changed order of include's in implode.h to make tailor.h show up first.
  695. X13. Added Convex mods and make target.
  696. X14. Fixed path delimiter under VMS for unship.
  697. X15. Added ship to makevms.com.
  698. X16. Put in new copyright messages.
  699. X17. Added aix make target.
  700. X18. Fixed zipsplit.idx to start counting at one like the file names.
  701. X19. Changed -a (append VMS version number) to -w to leave -a open for a
  702. X    possible future option.
  703. X20. Back to separate makefiles for Microsoft and Borland (.msc and .bor).
  704. X21. Workaround in fileio.c for Borland stat() bug: stat() succeeds for wild
  705. X    card names that match existing files.
  706. X22. Added "(did you remember to use binary mode when you transferred it?)"
  707. X    to the "probably not a zip file" warning.
  708. X23. Changed utilities to append .zip only when the zip file name does not
  709. X    contain a dot.
  710. X24. At least mentioned the other utilities in zip.doc (zipcloak, ship, etc.),
  711. X    and documented upper case matching of names when using -d under MSDOS.
  712. X25. Fixed bug in MSDOS version: zip foo c:autoexec.bat wouldn't work.
  713. X26. Added hidden/system attribute bug to BUGS in zip.1
  714. X27. Fixed recognition of unship in ship when unship is in a path.
  715. X28. Added non-stream-LF VMS bug to zip.1 bug list.
  716. X29. Fixed bug in #23 above when path has dots.  Documented #23 in zip.1.
  717. X30. Show disclaimer only for -l, add -h and -l to zip utilities.
  718. X31. Applied Minix patches.
  719. END_OF_FILE
  720. if test 36825 -ne `wc -c <'history'`; then
  721.     echo shar: \"'history'\" unpacked with wrong size!
  722. fi
  723. # end of 'history'
  724. fi
  725. if test -f 'ship.c' -a "${1}" != "-c" ; then 
  726.   echo shar: Will not clobber existing file \"'ship.c'\"
  727. else
  728. echo shar: Extracting \"'ship.c'\" \(38393 characters\)
  729. sed "s/^X//" >'ship.c' <<'END_OF_FILE'
  730. X/* ship.c -- Not copyrighted 1991 Mark Adler */
  731. X
  732. X#define SHIPVER "ship version 1.0  September 29, 1991  Mark Adler"
  733. X
  734. X/* Command for mailing (-m): the %s's are, in order, the subject prefix,
  735. X   the part number (always of the form "partnnnn"), the subject suffix
  736. X   (empty or " (last)" if the last part), the mailing address, and the
  737. X   name of the temporary file begin mailed.  The command "Mail" is for BSD
  738. X   systems.  You may need to change it to "mailx" for System V Unix, using
  739. X   the compile option "-DMAILX".  Also, on Sperry (Unisys?) SysV.3 systems,
  740. X   you might try the command name "v6mail". */
  741. X
  742. X#ifdef DIRENT           /* If compiled with zip, DIRENT implies System V */
  743. X#  define MAILX
  744. X#endif /* DIRENT */
  745. X
  746. X#ifdef sun              /* Except Sun's use DIRENT, but have Mail */
  747. X#  ifdef MAILX
  748. X#    undef MAILX
  749. X#  endif /* MAILX */
  750. X#endif /* sun */
  751. X
  752. X#ifdef sgi              /* Silicon Graphics that way too */
  753. X#  ifdef MAILX
  754. X#    undef MAILX
  755. X#  endif /* MAILX */
  756. X#endif /* sgi */
  757. X
  758. X#ifdef VMS
  759. X#  define TMPNAME "_SXXXXXX."
  760. X#  define MAILCMD "mail %s /subj=\"%s %s%s\" \"%s\""
  761. X#  define PATHCUT ']'
  762. X#else /* !VMS */
  763. X#  define TMPNAME "_SXXXXXX"
  764. X#  ifdef MAILX
  765. X#    define MAILCMD "mailx -s \"%s %s%s\" \"%s\" < %s"
  766. X#  else /* !MAILX */
  767. X#    define MAILCMD "Mail -s \"%s %s%s\" \"%s\" < %s"
  768. X#  endif /* ?MAILX */
  769. X#  define PATHCUT '/'
  770. X#endif /* ?VMS */
  771. X
  772. X/*
  773. X
  774. SHIP -
  775. X
  776. X  Ship is a program for sending binary files through email.  It is designed
  777. X  to supplant uuencode and uudecode.  Ship encodes approximately 6.23 bits
  778. X  per character mailed, compared to uuencode's 5.73 bits per character.
  779. X
  780. X  Ship also has these features: a 32-bit CRC check on each file; automatic
  781. X  splitting of the ship output into multiple, smaller files for speedier
  782. X  mailing; automatic mailing of ship's output, with subject lines for
  783. X  multiple parts; and a check on the sequence of parts when unshipping.
  784. X
  785. X  Usage:
  786. X
  787. X       ship [-nnn] [-m address] [-s subject] file ...
  788. X
  789. X  where nnn is the maximum number of K bytes for each output file, address
  790. X  is the address to send mail to, subject is a Subject" line prefix, and
  791. X  file ... is a list of files to ship.  If no options are given, ship
  792. X  outputs to stdout.  The simplest use is:
  793. X
  794. X       ship foo > x
  795. X
  796. X  where foo is converted into the mailable file, x.
  797. X
  798. X  When -nnn is specified, but -m is not, ship writes to the files
  799. X  part0001, part0002, etc., where each file has nnn or less K bytes.  For
  800. X  example:
  801. X
  802. X       ship -25 bigfoo
  803. X
  804. X  will write however many 25K byte or less ship files is needed to contain
  805. X  bigfoo.  If, say, six files are needed, then the files part0001 to part0006
  806. X  will be written.
  807. X
  808. X  When using -m, nothing is written, either to files or to stdout; rather,
  809. X  the output is mailed to the specified address.  If -nnn is also specified,
  810. X  then the parts are mailed separately with the subject lines part0001, etc.
  811. X  If -nnn is not specified, then only one part (the whole thing) is mailed
  812. X  with the subject line "part0001".  For example:
  813. X
  814. X       ship -25 -m fred bigfoo
  815. X
  816. X  will mail the six parts of bigfoo to fred.
  817. X
  818. X  Any number of files can be shipped at once.  They become part of one long
  819. X  ship stream, so if, for example -25 is specified, all but the last part
  820. X  will have about 25K bytes.  For example:
  821. X
  822. X       ship -25 -m fred fee fi fo fum
  823. X
  824. X  will send the files fee, fi, fo, and fum to fred.
  825. X
  826. X  Fred will get several mail messages with the subject lines part0001, etc.
  827. X  He can then save those messages as the files, say, p1, p2, p3, ...
  828. X  Then he can use the command:
  829. X
  830. X       ship -u p?
  831. X
  832. X  to recreate bigfoo, or fee fi fo and fum, depending on what he was sent.
  833. X  If Fred saved the wrong numbers, ship will detect this and report a
  834. X  sequence error.
  835. X
  836. X  Note: there is enough information in the shipped parts to determine the
  837. X  correct sequence.  A future version of ship will prescan the files to
  838. X  determine the sequence, and then process them in the correct order.
  839. X
  840. X  If a file being received already exists, ship -u will report an error
  841. X  and exit.  The -o option avoids this and allows ship to overwrite existing
  842. X  files.  The -o option must follow the -u option:
  843. X
  844. X       ship -u -o p?
  845. X
  846. X  In addition to the -u option, ship will unship if it sees that its name is
  847. X  unship.  On Unix systems, this can be done simply by linking the executable
  848. X  to unship:
  849. X
  850. X       ln ship unship 
  851. X
  852. X  Ship can also be used as a filter.  The special file name "-" means stdin.
  853. X  For example:
  854. X
  855. X       tar covf - foodir | compress | ship -25 -m fred -
  856. X
  857. X  will tar the directory foodir, compress it, and ship it to fred in 25K byte
  858. X  pieces.  Then, after Fred saves the files as p01, etc. at the other, end,
  859. X  he can:
  860. X
  861. X       ship -u p? | zcat | tar xovf -
  862. X
  863. X  which will recreate the directory foobar and its contents.  ship -u knows
  864. X  to write to stdout, since the original ship put the special file name "-"
  865. X  in the first part.
  866. X
  867. X  Ship uses a base 85 coding that needs 32-bit multiplication and division.
  868. X  This can be slow on 16-bit machines, so ship provides a fast encoding
  869. X  method by specifying the -f option.  This method is somewhat faster even
  870. X  on 32-bit machines, and has approximately a 1% penalty in the size of the
  871. X  encoded result (-f gives 6.26 bits per character, on the average).  The -f
  872. X  option need only be used when shipping--unshipping (ship -u) automatically
  873. X  detects the encoding used.  For example:
  874. X
  875. X       ship -f -25 -m fred foo
  876. X
  877. X  will send foo to fred in 25K byte pieces using the fast encoding method.
  878. X  You don't need to tell Fred, since ship -u will figure that out for him.
  879. X
  880. X  The fast encoding method is probabilistic, so it's possible for the size
  881. X  penalty to be worse than 1%, and it's also possible for the fast encoding
  882. X  to produce a smaller result than base 85 encoding would, all depending on
  883. X  the data.
  884. X
  885. X  The -q option can be used with either ship or unship (ship -u) for quiet
  886. X  operation--informational messages are inhibited.
  887. X
  888. X  You can find out the version of ship and get the command usage by using
  889. X  "ship -h" or "ship -?".  The version number and date and help will be
  890. X  printed, and ship will exit (the rest of the command line is ignored).
  891. X
  892. X  Acknowledgements:
  893. X
  894. X  The hard-arithmetic coding algorithm was blatantly stolen from Peter
  895. X  Gutmann's pgencode/pgdecode programs posted on comp.compression, with
  896. X  modifications to use 86 instead of 94 characters, and to make zeros encode
  897. X  better than, rather than worse than other bytes.  (As Stravinsky once said:
  898. X  "Mediocre composers plagiarize.  Great composers steal.")
  899. X
  900. X*/
  901. X
  902. X/* tailor.h -- Not copyrighted 1991 Mark Adler */
  903. X
  904. X/* const's are inconsistently used across ANSI libraries--kill for all
  905. X   header files. */
  906. X#define const
  907. X
  908. X
  909. X/* Use prototypes and ANSI libraries if __STDC__ */
  910. X#ifdef __STDC__
  911. X#  ifndef PROTO
  912. X#    define PROTO
  913. X#  endif /* !PROTO */
  914. X#  define MODERN
  915. X#endif /* __STDC__ */
  916. X
  917. X
  918. X/* Use prototypes and ANSI libraries if Silicon Graphics */
  919. X#ifdef sgi
  920. X#  ifndef PROTO
  921. X#    define PROTO
  922. X#  endif /* !PROTO */
  923. X#  define MODERN
  924. X#endif /* sgi */
  925. X
  926. X
  927. X/* Define MSDOS for Turbo C as well as Microsoft C */
  928. X#ifdef __POWERC                 /* For Power C too */
  929. X#  define __TURBOC__
  930. X#endif /* __POWERC */
  931. X#ifdef __TURBOC__
  932. X#  ifndef MSDOS
  933. X#    define MSDOS
  934. X#  endif /* !MSDOS */
  935. X#endif /* __TURBOC__ */
  936. X
  937. X
  938. X/* Use prototypes and ANSI libraries if Microsoft or Borland C */
  939. X#ifdef MSDOS
  940. X#  ifndef PROTO
  941. X#    define PROTO
  942. X#  endif /* !PROTO */
  943. X#  define MODERN
  944. X#endif /* MSDOS */
  945. X
  946. X
  947. X/* Turn off prototypes if requested */
  948. X#ifdef NOPROTO
  949. X#  ifdef PROTO
  950. X#    undef PROTO
  951. X#  endif /* PROTO */
  952. X#endif /* NOPROT */
  953. X
  954. X
  955. X/* Used to remove arguments in function prototypes for non-ANSI C */
  956. X#ifdef PROTO
  957. X#  define OF(a) a
  958. X#else /* !PROTO */
  959. X#  define OF(a) ()
  960. X#endif /* ?PROTO */
  961. X
  962. X
  963. X/* Allow far and huge allocation for small model (Microsoft C or Turbo C) */
  964. X#ifdef MSDOS
  965. X#  ifdef __TURBOC__
  966. X#    include <alloc.h>
  967. X#  else /* !__TURBOC__ */
  968. X#    include <malloc.h>
  969. X#    define farmalloc _fmalloc
  970. X#    define farfree   _ffree
  971. X#  endif /* ?__TURBOC__ */
  972. X#else /* !MSDOS */
  973. X#  define huge
  974. X#  define far
  975. X#  define near
  976. X#  define farmalloc malloc
  977. X#  define farfree   free
  978. X#endif /* ?MSDOS */
  979. X
  980. X
  981. X/* Define MSVMS if either MSDOS or VMS defined */
  982. X#ifdef MSDOS
  983. X#  define MSVMS
  984. X#else /* !MSDOS */
  985. X#  ifdef VMS
  986. X#    define MSVMS
  987. X#  endif /* VMS */
  988. X#endif /* ?MSDOS */
  989. X
  990. X
  991. X/* Define void, voidp, and extent (size_t) */
  992. X#include <stdio.h>
  993. X#ifdef MODERN
  994. X#  ifndef M_XENIX
  995. X#    include <stddef.h>
  996. X#  endif /* !M_XENIX */
  997. X#  include <stdlib.h>
  998. X   typedef size_t extent;
  999. X   typedef void voidp;
  1000. X#else /* !MODERN */
  1001. X   typedef unsigned int extent;
  1002. X#  define void int
  1003. X   typedef char voidp;
  1004. X#endif /* ?MODERN */
  1005. X
  1006. X/* Get types and stat */
  1007. X#ifdef VMS
  1008. X#  include <types.h>
  1009. X#  include <stat.h>
  1010. X#else /* !VMS */
  1011. X#  include <sys/types.h>
  1012. X#  include <sys/stat.h>
  1013. X#endif /* ?VMS */
  1014. X
  1015. X
  1016. X/* Cheap fix for unlink on VMS */
  1017. X#ifdef VMS
  1018. X#  define unlink delete
  1019. X#endif /* VMS */
  1020. X
  1021. X
  1022. X/* For Pyramid */
  1023. X#ifdef pyr
  1024. X#  define strrchr rindex
  1025. X#  define ZMEM
  1026. X#endif /* pyr */
  1027. X
  1028. X
  1029. X/* File operations--use "b" for binary if allowed */
  1030. X#ifdef MODERN
  1031. X#  define FOPR "rb"
  1032. X#  define FOPM "r+b"
  1033. X#  define FOPW "w+b"
  1034. X#else /* !MODERN */
  1035. X#  define FOPR "r"
  1036. X#  define FOPM "r+"
  1037. X#  define FOPW "w+"
  1038. X#endif /* ?MODERN */
  1039. X
  1040. X
  1041. X/* Fine tuning */
  1042. X#ifndef MSDOS
  1043. X#   define BSZ 8192   /* Buffer size for files */
  1044. X#else /* !MSDOS */
  1045. X#   define BSZ 4096   /* Keep precious NEAR space */
  1046. X    /* BSZ can't be 8192 even for compact model because of 64K limitation
  1047. X     * in im_lmat.c. If you run out of memory when processing a large number
  1048. X     * files, use the compact model and reduce BSZ to 2048 here and in
  1049. X     * im_lm.asm.
  1050. X     */
  1051. X#endif /* ?MSDOS */
  1052. X
  1053. X/* end of tailor.h */
  1054. X
  1055. X#ifdef MODERN
  1056. X#  include <string.h>
  1057. X#else /* !MODERN */
  1058. X   voidp *malloc();
  1059. X   long atol();
  1060. X   char *strcpy();
  1061. X   char *strrchr();
  1062. X#endif /* ?MODERN */
  1063. X
  1064. X/* Library functions not in (most) header files */
  1065. char *mktemp OF((char *));
  1066. int unlink OF((char *));
  1067. X
  1068. X#ifdef MSDOS            /* Use binary mode for binary files */
  1069. X#  include <io.h>
  1070. X#  include <fcntl.h>
  1071. X#endif /* MSDOS */
  1072. X
  1073. X
  1074. X#define LNSZ 1025       /* size of line buffer */
  1075. X
  1076. typedef unsigned long ulg;      /* 32-bit unsigned integer */
  1077. X
  1078. typedef struct {        /* associates a CRC with a file */
  1079. X  FILE *f;              /* pointer to associated file stream */
  1080. X  ulg c;                /* CRC register */
  1081. X  ulg b;                /* four byte buffer */
  1082. X  int n;                /* buffer count */
  1083. X} cfile;
  1084. X
  1085. X
  1086. X/* Function prototypes */
  1087. X#ifdef MODERN
  1088. X   void err(int, char *);
  1089. X   cfile *chook(FILE *);
  1090. X   char *nopath(char *);
  1091. X   void newship(void);
  1092. X   void endship(int);
  1093. X   void newline(char *);
  1094. X   void ship(char *, FILE *);
  1095. X   void mkinv(void);
  1096. X   void decode(unsigned char *, cfile *);
  1097. X   void unship(char **, int, int);
  1098. X   void help(void);
  1099. X   void main(int, char **);
  1100. X#endif /* MODERN */
  1101. X
  1102. X
  1103. X
  1104. X/* Globals for ship() */
  1105. char sname[9];          /* current ship file name */
  1106. XFILE *sfile;            /* current ship file */
  1107. ulg slns;               /* number of lines written to ship file */
  1108. ulg slmax;              /* maximum number of lines per ship file */
  1109. int fast;               /* true for arithmetic coding, else base 85 */
  1110. int mail;               /* true if mailing */
  1111. char mpspc[9];          /* prealloced space for prefix */
  1112. char *mprefix = mpspc;  /* identification for this mailing */
  1113. char *mdest;            /* mail destination */
  1114. char mname[10];         /* temporary file name if mailing */
  1115. ulg ccnt;               /* count of bytes read or written */
  1116. int noisy = 1;          /* false to inhibit informational messages */
  1117. X
  1118. X
  1119. X
  1120. X/* Errors */
  1121. X#define SE_ARG 1
  1122. X#define SE_FIND 2
  1123. X#define SE_NONE 3
  1124. X#define SE_PART 4
  1125. X#define SE_FORM 5
  1126. X#define SE_CONT 6
  1127. X#define SE_CRC 7
  1128. X#define SE_MAIL 8
  1129. X#define SE_OVER 9
  1130. X#define SE_FULL 10
  1131. X#define SE_MANY 11
  1132. X#define SE_MEM 12
  1133. char *errors[] = {
  1134. X  /* 1 */ "invalid argument ",
  1135. X  /* 2 */ "could not find ",
  1136. X  /* 3 */ "no files received",
  1137. X  /* 4 */ "unfinished file ",
  1138. X  /* 5 */ "invalid ship format in ",
  1139. X  /* 6 */ "wrong sequence for ",
  1140. X  /* 7 */ "CRC check failed on ",
  1141. X  /* 8 */ "mail command failed: ",
  1142. X  /* 9 */ "attempted to overwrite ",
  1143. X  /* 10 */ "could not write to ",
  1144. X  /* 11 */ "too many output files!",
  1145. X  /* 12 */ "out of memory"
  1146. X};
  1147. X
  1148. X
  1149. X/* Set of 86 characters used for the base 85 digits (last one not used), and
  1150. X   the 86 character arithmetic coding.  Selected to be part of both the ASCII
  1151. X   printable characters, and the common EBCDIC printable characters whose
  1152. X   ASCII translations are universal. */
  1153. unsigned char safe[] = {
  1154. X        '{','"','#','$','%','&','\'','(',')','*','+',',','-','.','/',
  1155. X        '0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?','@',
  1156. X        'A','B','C','D','E','F','G','H','I','J','K','L','M',
  1157. X        'N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_',
  1158. X        'a','b','c','d','e','f','g','h','i','j','k','l','m',
  1159. X        'n','o','p','q','r','s','t','u','v','w','x','y','z','}'};
  1160. X
  1161. X#define LOWSZ (sizeof(safe)-64)         /* low set size for fast coding */
  1162. X
  1163. X/* Special replacement pairs--if first of each pair is received, it is
  1164. X   treated like the second member of the pair.  You're probably
  1165. X   wondering why.  The first pair is for compatibility with an
  1166. X   earlier version of ship that used ! for the base 85 zero digit.
  1167. X   However, there exist ASCII-EBCDIC translation tables that don't
  1168. X   know about exclamation marks.  The second set has mysterious
  1169. X   historical origins that are best left unspoken ... */
  1170. unsigned char aliases[] = {'!','{','|','+',0};
  1171. X
  1172. X/* Inverse of safe[], filled in by mkinv() */
  1173. unsigned char invsafe[256];
  1174. X
  1175. X/* Table of CRC-32's of all single byte values (made by makecrc.c) */
  1176. ulg crctab[] = {
  1177. X  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
  1178. X  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
  1179. X  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
  1180. X  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
  1181. X  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
  1182. X  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
  1183. X  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
  1184. X  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
  1185. X  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
  1186. X  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
  1187. X  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
  1188. X  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  1189. X  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
  1190. X  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
  1191. X  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
  1192. X  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
  1193. X  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
  1194. X  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
  1195. X  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
  1196. X  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
  1197. X  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
  1198. X  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
  1199. X  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
  1200. X  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  1201. X  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
  1202. X  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
  1203. X  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
  1204. X  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
  1205. X  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
  1206. X  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
  1207. X  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
  1208. X  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
  1209. X  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
  1210. X  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
  1211. X  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
  1212. X  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  1213. X  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
  1214. X  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
  1215. X  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
  1216. X  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
  1217. X  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
  1218. X  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
  1219. X  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
  1220. X  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
  1221. X  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
  1222. X  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
  1223. X  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
  1224. X  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  1225. X  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
  1226. X  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
  1227. X  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
  1228. X  0x2d02ef8dL
  1229. X};
  1230. X
  1231. X/* Macro to update the CRC shift register one byte at a time */
  1232. X#define CRC(c,b) (crctab[((int)(c)^(int)(b))&0xff]^((c)>>8))
  1233. X
  1234. X
  1235. char *errname = "ship error";
  1236. char *warname = "ship warning";
  1237. X
  1238. void err(n, m)
  1239. int n;                  /* error number */
  1240. char *m;                /* additional error information */
  1241. X{
  1242. X  if (n == SE_FIND || n == SE_FULL)
  1243. X    perror(errname);
  1244. X  fputs(errname, stderr);
  1245. X  fputs(": ", stderr);
  1246. X  fputs(errors[n - 1], stderr);
  1247. X  fputs(m, stderr);
  1248. X  putc('\n', stderr);
  1249. X  if (*mname)
  1250. X    unlink(mname);
  1251. X#ifdef VMS
  1252. X  exit(0);
  1253. X#else /* !VMS */
  1254. X  exit(n);
  1255. X#endif /* ?VMS */
  1256. X}
  1257. X
  1258. X
  1259. cfile *chook(f)
  1260. XFILE *f;                /* file stream */
  1261. X/* Inherit the file stream structure and add a CRC and buffer for appending
  1262. X   a CRC on reads and checking the CRC on writes.  Return a pointer to the
  1263. X   cfile structure, or NULL if the malloc() failed.  Also, if MSDOS, set the
  1264. X   file mode to binary to avoid LF<->CRLF conversions. */
  1265. X{
  1266. X  cfile *c;             /* allocated cfile structure */
  1267. X
  1268. X#ifdef MSDOS
  1269. X  /* Set file mode to binary for MSDOS systems */
  1270. X  setmode(fileno(f), O_BINARY);
  1271. X#endif /* MSDOS */
  1272. X
  1273. X  /* Allocate and fill structure */
  1274. X  if ((c = (cfile *)malloc(sizeof(cfile))) != NULL)
  1275. X  {
  1276. X    c->f = f;                           /* file stream */
  1277. X    c->b = 0;                           /* empty fifo (for output) */
  1278. X    c->c = 0xffffffffL;                 /* preload CRC register */
  1279. X    c->n = 0;                           /* fifo is empty (output) or */
  1280. X  }                                     /*  no CRC bytes given (input) */
  1281. X  return c;
  1282. X}
  1283. X
  1284. X
  1285. X
  1286. X/* cgetc(x)--like getc(f), but appends a 32-bit CRC to the end of the stream.
  1287. X   Return the byte read (the last four of which will be the CRC) or EOF. */
  1288. X#define cgete(x) (x->n==4?EOF:(x->c=x->n++?x->c>>8:~x->c,(int)x->c&0xff))
  1289. X#define cgetc(x) (x->n==0&&(b=getc(x->f))!=EOF?(ccnt++,x->c=CRC(x->c,b),b):cgete(c))
  1290. X
  1291. X
  1292. X/* cputc(d,x)--like putc(d,f), but delays four bytes and computes a CRC.
  1293. X   x is a cfile *, and d is expected to be an ulg. */
  1294. X#define cputf(x) (int)(x->c=CRC(x->c,x->b),putc((int)x->b&0xff,x->f),ccnt++)
  1295. X#define cputc(d,x) (x->n!=4?x->n++:cputf(x),x->b=(x->b>>8)+((ulg)(d)<<24))
  1296. X
  1297. X
  1298. char *nopath(p)
  1299. char *p;                /* full file name */
  1300. X/* Extract just the name of file--remove and subdirectories or devices */
  1301. X{
  1302. X#ifdef MSDOS
  1303. X  char *q = "/\\:";     /* MSDOS delimiters */
  1304. X#else /* !MSDOS */
  1305. X#ifdef VMS
  1306. X  char *q = "]:";       /* VMS delimiters */
  1307. X#else /* !VMS */
  1308. X  char *q = "/";        /* Unix delimiter */
  1309. X#endif /* ?VMS */
  1310. X#endif /* ?MSDOS */
  1311. X  char *r;              /* result of strrchr() */
  1312. X
  1313. X  while (*q)
  1314. X    if ((r = strrchr(p, *q++)) != NULL)
  1315. X      p = r + 1;
  1316. X  return p;
  1317. X}
  1318. X
  1319. X
  1320. void newship()
  1321. X/* Open up a new ship file to write to */
  1322. X{
  1323. X  int i;                /* scans down name to increment */
  1324. X
  1325. X  for (i = 7; i > 3; i--)
  1326. X    if (++sname[i] > '9')
  1327. X      sname[i] = '0';
  1328. X    else
  1329. X      break;
  1330. X  if (i == 3)
  1331. X    err(SE_MANY, "");
  1332. X  if ((sfile = fopen(mail ? mktemp(strcpy(mname, TMPNAME)) : sname,
  1333. X                     "w")) == NULL)
  1334. X    err(SE_FULL, mail ? mname : sname);
  1335. X  slns = 0;
  1336. X}
  1337. X
  1338. X
  1339. void endship(e)
  1340. int e;          /* true if ending the last ship file */
  1341. X/* Finish off current ship file */
  1342. X{
  1343. X  char *s;              /* malloc'd space for mail command */
  1344. X
  1345. X  if (ferror(sfile) || fclose(sfile))
  1346. X    err(SE_FULL, mail ? mname : sname);
  1347. X  if (mail)
  1348. X  {
  1349. X    if ((s = malloc(strlen(MAILCMD)- 5*2 + strlen(mprefix) + strlen(sname) +
  1350. X                    (e ? 7 : 0) + strlen(mdest) + strlen(mname) + 1)) == NULL)
  1351. X      err(SE_MEM, "");
  1352. X#ifdef VMS
  1353. X    sprintf(s, MAILCMD, mname, mprefix, sname, e ? " (last)" : "", mdest);
  1354. X    if (!system(s))             /* this string fits on one line */
  1355. X      err(SE_MAIL, "system() call is not supported on this machine");
  1356. X#else /* !VMS */
  1357. X    sprintf(s, MAILCMD, mprefix, sname, e ? " (last)" : "", mdest, mname);
  1358. X    if (system(s))
  1359. X      err(SE_MAIL, s);
  1360. X#endif /* ?VMS */
  1361. X    free((voidp *)s);
  1362. X    unlink(mname);
  1363. X    *mname = 0;
  1364. X  }
  1365. X}
  1366. X
  1367. X
  1368. void newline(p)
  1369. char *p;                /* name of the input file */
  1370. X/* Add a new line inside a ship file, possibly cut the file */
  1371. X{
  1372. X  putc('\n', sfile);
  1373. X  slns++;
  1374. X  if (slmax && slns >= slmax - 2)
  1375. X  {
  1376. X    putc('$', sfile);
  1377. X    if (fast)
  1378. X      fputs(" f", sfile);
  1379. X    fputs("\nmore\n", sfile);
  1380. X    endship(0);
  1381. X    newship();
  1382. X    fprintf(sfile, "$%s\ncont %lu %s\n", fast ? " f" : "", ccnt, nopath(p));
  1383. X    slns += 2;
  1384. X  }
  1385. X}
  1386. X
  1387. X
  1388. X/* Macro to avoid leading dots.  It assumes i==0 at the beginning of a line
  1389. X   and that b is an available int.  c is only evaluated once. */
  1390. X#define sputc(c,f) (i==0?((b=(c))=='.'?putc(' ',f):0,putc(b,f)):putc(c,f))
  1391. X
  1392. X
  1393. void ship(p, f)
  1394. char *p;                /* name of the input file */
  1395. XFILE *f;                /* input file */
  1396. X/* Encode the binary file f. */
  1397. X{
  1398. X  int b;                /* character just read */
  1399. X  cfile *c;             /* checked file stream */
  1400. X  int i;                /* how much is written on line so far */
  1401. X  int j;                /* how much is in bit buffer */
  1402. X
  1403. X  /* Set up output file if needed */
  1404. X  if ((mail || slmax) && sfile == stdout)
  1405. X  {
  1406. X    strcpy(sname, "part0000");
  1407. X    newship();
  1408. X  }
  1409. X
  1410. X  /* Write header */
  1411. X  if ((c = chook(f)) == NULL)
  1412. X    err(SE_MEM, "");
  1413. X  ccnt = 0;
  1414. X  if (slmax && slns >= slmax - 5) 
  1415. X  {
  1416. X    endship(0);
  1417. X    newship();
  1418. X  }
  1419. X  fprintf(sfile, "$%s\nship %s\n", fast ? " f" : "", nopath(p));
  1420. X  slns += 2;
  1421. X
  1422. X  /* Encode the file, writing to sfile */
  1423. X  if (fast)
  1424. X  {
  1425. X    int d;              /* accumulates bits (never more than 14) */
  1426. X
  1427. X    d = j = i = 0;
  1428. X    while ((b = cgetc(c)) != EOF)
  1429. X    {
  1430. X      d |= b << j;
  1431. X      j += 8;
  1432. X      if ((d & 0x3f) >= LOWSZ)
  1433. X      {
  1434. X        sputc((int)(safe[(d & 0x3f) + LOWSZ]), sfile);
  1435. X        d >>= 6;
  1436. X        j -= 6;
  1437. X      }
  1438. X      else
  1439. X      {
  1440. X        sputc((int)(safe[(d & 0x3f) + (d & 0x40 ? LOWSZ : 0)]), sfile);
  1441. X        d >>= 7;
  1442. X        j -= 7;
  1443. X      }
  1444. X      if (++i == 79)
  1445. X      {
  1446. X        newline(p);
  1447. X        i = 0;
  1448. X      }
  1449. X      if (j >= 6 && (d & 0x3f) >= LOWSZ)
  1450. X      {
  1451. X        sputc((int)(safe[(d & 0x3f) + LOWSZ]), sfile);
  1452. X        d >>= 6;
  1453. X        j -= 6;
  1454. X        if (++i == 79)
  1455. X        {
  1456. X          newline(p);
  1457. X          i = 0;
  1458. X        }
  1459. X      }
  1460. X      else if (j >= 7)
  1461. X      {
  1462. X        sputc((int)(safe[(d & 0x3f) + (d & 0x40 ? LOWSZ : 0)]), sfile);
  1463. X        d >>= 7;
  1464. X        j -= 7;
  1465. X        if (++i == 79)
  1466. X        {
  1467. X          newline(p);
  1468. X          i = 0;
  1469. X        }
  1470. X      }
  1471. X    }
  1472. X    free((voidp *)c);
  1473. X
  1474. X    /* Write leftover bits */
  1475. X    if (j)
  1476. X    {
  1477. X      sputc((int)(safe[d + (d < LOWSZ ? 0 : LOWSZ)]), sfile);
  1478. X      putc('\n', sfile);
  1479. X      slns++;
  1480. X    }
  1481. X    else if (i)
  1482. X    {
  1483. X      putc('\n', sfile);
  1484. X      slns++;
  1485. X    }
  1486. X  }
  1487. X  else
  1488. X  {
  1489. X    ulg d;              /* accumulates bytes */
  1490. X
  1491. X    d = j = i = 0;
  1492. X    while ((b = cgetc(c)) != EOF)
  1493. X    {
  1494. X      d += ((ulg)b) << j;
  1495. X      if ((j += 8) == 32)
  1496. X      {
  1497. X        sputc((int)(safe[(int)(d % 85)]), sfile);  d /= 85;
  1498. X        putc((int)(safe[(int)(d % 85)]), sfile);  d /= 85;
  1499. X        putc((int)(safe[(int)(d % 85)]), sfile);  d /= 85;
  1500. X        putc((int)(safe[(int)(d % 85)]), sfile);  d /= 85;
  1501. X        putc((int)(safe[(int)d]), sfile);
  1502. X        if (++i == 15)                  /* each line is <= 75 characters */
  1503. X        {
  1504. X          newline(p);
  1505. X          i = 0;
  1506. X        }
  1507. X        d = j = 0;
  1508. X      }
  1509. X    }
  1510. X    free((voidp *)c);
  1511. X  
  1512. X    /* Write leftover data */
  1513. X    if (j)
  1514. X    {
  1515. X      j >>= 3;
  1516. X      sputc((int)(safe[(int)(d % 85)]), sfile);
  1517. X      while (j--)
  1518. X      {
  1519. X        d /= 85;
  1520. X        putc((int)(safe[(int)(d % 85)]), sfile);
  1521. X      }
  1522. X      putc('\n', sfile);
  1523. X      slns++;
  1524. X    }
  1525. X    else if (i)
  1526. X    {
  1527. X      putc('\n', sfile);
  1528. X      slns++;
  1529. X    }
  1530. X  }
  1531. X  putc('$', sfile);
  1532. X  if (fast)
  1533. X    fputs(" f", sfile);
  1534. X  fputs("\nend\n", sfile);
  1535. X  slns += 2;
  1536. X  if (ferror(sfile) || fflush(sfile))
  1537. X    err(SE_FULL, mail ? mname : sname);
  1538. X  if (noisy)
  1539. X    fprintf(stderr, "%s shipped\n", p);
  1540. X}
  1541. X
  1542. X
  1543. void mkinv()
  1544. X/* Build invsafe[], the inverse of safe[]. */
  1545. X{
  1546. X  int i;
  1547. X
  1548. X  for (i = 0; i < 256; i++)
  1549. X    invsafe[i] = 127;
  1550. X  for (i = 0; i < sizeof(safe); i++)
  1551. X    invsafe[safe[i]] = (char)i;
  1552. X  for (i = 0; aliases[i]; i += 2)
  1553. X    invsafe[aliases[i]] = invsafe[aliases[i + 1]];
  1554. X}
  1555. X
  1556. X
  1557. unsigned int decb;      /* bit buffer for decode */
  1558. unsigned int decn;      /* number of bits in decb */
  1559. X
  1560. void decode(s, c)
  1561. unsigned char *s;       /* data to decode */
  1562. cfile *c;               /* binary output file */
  1563. X/* Decode s, a string of base 85 digits or, if fast is true, a string of safe
  1564. X   characters generated arithmetically, into its binary equivalent, writing
  1565. X   the result to c, using cputc(). */
  1566. X{
  1567. X  int b;                /* state of line loop, next character */
  1568. X  int k;                /* counts bits or digits read */
  1569. X  /* powers of 85 table for decoding */
  1570. X  static ulg m[] = {1L,85L,85L*85L,85L*85L*85L,85L*85L*85L*85L};
  1571. X
  1572. X  if (fast)
  1573. X  {
  1574. X    unsigned int d;     /* disperses bits */
  1575. X
  1576. X    d = decb;
  1577. X    k = decn;
  1578. X    while ((b = *s++) != 0)
  1579. X      if ((b = invsafe[b]) < sizeof(safe))
  1580. X      {
  1581. X        if (b < LOWSZ)
  1582. X        {
  1583. X          d |= b << k;
  1584. X          k += 7;
  1585. X        }
  1586. X        else if ((b -= LOWSZ) < LOWSZ)
  1587. X        {
  1588. X          d |= (b + 0x40) << k;
  1589. X          k += 7;
  1590. X        }
  1591. X        else
  1592. X        {
  1593. X          d |= b << k;
  1594. X          k += 6;
  1595. X        }
  1596. X        if (k >= 8)
  1597. X        {
  1598. X          cputc(d, c);
  1599. X          d >>= 8;
  1600. X          k -= 8;
  1601. X        }
  1602. X      }
  1603. X    decb = d;
  1604. X    decn = k;
  1605. X  }
  1606. X  else
  1607. X  {
  1608. X    ulg d;              /* disperses bytes */
  1609. X
  1610. X    d = k = 0;
  1611. X    while ((b = *s++) != 0)
  1612. X      if ((b = invsafe[b]) < 85)
  1613. X      {
  1614. X        d += m[k] * b;
  1615. X        if (++k == 5)
  1616. X        {
  1617. X          cputc(d, c);  d >>= 8;
  1618. X          cputc(d, c);  d >>= 8;
  1619. X          cputc(d, c);  d >>= 8;
  1620. X          cputc(d, c);
  1621. X          d = k = 0;
  1622. X        }
  1623. X      }
  1624. X    if (--k > 0)
  1625. X    {
  1626. X      while (--k)
  1627. X      {
  1628. X        cputc(d, c);
  1629. X        d >>= 8;
  1630. X      }
  1631. X      cputc(d, c);
  1632. X    }
  1633. X  }
  1634. X}
  1635. X
  1636. X
  1637. void unship(v, g, o)
  1638. char **v;               /* arguments */
  1639. int g;                  /* number of arguments */
  1640. int o;                  /* overwrite flag */
  1641. X/* Extract from the files named in the arguments the files that were
  1642. X   encoded by ship.  If an argument is "-", then stdin is read. */
  1643. X{
  1644. X  int b;                /* state of line loop */
  1645. X  cfile *c;             /* output binary file */
  1646. X  FILE *f;              /* output file */
  1647. X  char *h;              /* name of current ship file */
  1648. X  char l[LNSZ];         /* line buffer on input */
  1649. X  int n;                /* next argument to use for input */
  1650. X  char *p;              /* modifies line buffer */
  1651. X  char *q;              /* scans continuation line */
  1652. X  char *r;              /* name of output binary file */
  1653. X  FILE *s;              /* current ship file */
  1654. X  int z;                /* true if zero files received */
  1655. X
  1656. X  /* Build inverse table */
  1657. X  mkinv();
  1658. X
  1659. X  /* No input or output files initially */
  1660. X  s = NULL;
  1661. X  c = NULL;
  1662. X  h = r = NULL;
  1663. X
  1664. X  /* Loop on input files' lines */
  1665. X  z = 1;                                /* none received yet */
  1666. X  n = 0;                                /* start with file zero */
  1667. X  b = 2;                                /* not in body yet */
  1668. X  while (1)                             /* return on end of last file */
  1669. X  {
  1670. X    /* Get next line from list of files */
  1671. X    while (s == NULL || fgets(l, LNSZ, s) == NULL)
  1672. X    {
  1673. X      if (s != NULL)
  1674. X        fclose(s);
  1675. X      if (n >= g)
  1676. X      {
  1677. X        if (c != NULL)
  1678. X          err(SE_PART, r);
  1679. X        else if (z)
  1680. X          err(SE_NONE, "");
  1681. X        return;
  1682. X      }
  1683. X      if (v[n][0] == '-')
  1684. X        if (v[n][1])
  1685. X          err(SE_ARG, v[n]);
  1686. X        else
  1687. X        {
  1688. X          h = "stream stdin";
  1689. X          s = stdin;
  1690. X        }
  1691. X      else
  1692. X      {
  1693. X        h = v[n];
  1694. X        if ((s = fopen(h, "r")) == NULL)
  1695. X          err(SE_FIND, h);
  1696. X      }
  1697. X      n++;
  1698. X      b &= ~1;                          /* not in middle of line */
  1699. X    }
  1700. X
  1701. X    /* Strip control characters and leading blank space, if any */
  1702. X    for (q = l; *q && *q <= ' ' && *q != '\n'; q++)
  1703. X      ;
  1704. X    for (p = l; *q; q++)
  1705. X      if (*q >= ' ' || *q == '\n')
  1706. X        *p++ = *q;
  1707. X    *p = 0;
  1708. X
  1709. X    /* Based on current state, end or start on terminator.  States are:
  1710. X         b == 0:  at start of body or body terminator line
  1711. X         b == 1:  in middle of body line
  1712. X         b == 2:  at start of non-body line
  1713. X         b == 3:  in middle of non-body line
  1714. X         b == 4:  at information line
  1715. X    */
  1716. X    switch (b)
  1717. X    {
  1718. X    case 0:
  1719. X      if ((!fast && strcmp(l, "$\n") == 0) ||
  1720. X          (fast && strcmp(l, "$ f\n") == 0))
  1721. X      {
  1722. X        b = 4;
  1723. X        break;
  1724. X      }
  1725. X      /* fall through to case 1 */
  1726. X    case 1:
  1727. X      decode((unsigned char *)l, c);
  1728. X      b = l[strlen(l) - 1] != '\n';
  1729. X      break;
  1730. X    case 2:
  1731. X      if (strcmp(l, "$\n") == 0 || strcmp(l, "$ f\n") == 0)
  1732. X      {
  1733. X        fast = l[1] == ' ';
  1734. X        b = 4;
  1735. X        break;
  1736. X      }
  1737. X      /* fall through to case 3 */
  1738. X    case 3:
  1739. X      b = l[strlen(l)-1] == '\n' ? 2 : 3;
  1740. X      break;
  1741. X    case 4:
  1742. X      /* Possible information lines are ship, more, cont, and end */
  1743. X      if (l[b = strlen(l) - 1] != '\n')
  1744. X        err(SE_FORM, h);
  1745. X      l[b] = 0;
  1746. X      if (strncmp(l, "ship ", 5) == 0)
  1747. X      {
  1748. X        /* get name, open new output file */
  1749. X        if (c != NULL)
  1750. X          err(SE_FORM, h);
  1751. X        if ((r = malloc(b - 4)) == NULL)
  1752. X          err(SE_MEM, "");
  1753. X        strcpy(r, l + 5);
  1754. X        if (strcmp(r, "-") == 0)
  1755. X          f = stdout;
  1756. X#ifndef VMS     /* shouldn't have explicit version #, so VMS won't overwrite */
  1757. X        else if (!o && (f = fopen(r, "r")) != NULL)
  1758. X        {
  1759. X          fclose(f);
  1760. X          err(SE_OVER, r);
  1761. X        }
  1762. X#endif /* !VMS */
  1763. X        else if ((f = fopen(r, "w")) == NULL)
  1764. X          err(SE_FULL, r);
  1765. X        if ((c = chook(f)) == NULL)
  1766. X          err(SE_MEM, "");
  1767. X        b = decb = decn = 0;
  1768. X        ccnt = 0;
  1769. X      }
  1770. X      else if (strcmp(l, "more") == 0)
  1771. X      {
  1772. X        /* check if currently writing */
  1773. X        if (c == NULL)
  1774. X          err(SE_FORM, h);
  1775. X        b = 2;
  1776. X      }
  1777. X      else if (strncmp(l, "cont ", 5) == 0)
  1778. X      {
  1779. X        /* check name and file offset */
  1780. X        if (c == NULL)
  1781. X          err(SE_FORM, h);
  1782. X        for (q = l + 5; *q && *q != ' '; q++)
  1783. X          ;
  1784. X        if (*q == 0 || atol(l + 5) != ccnt + 4 + (decn != 0) ||
  1785. X            strcmp(q + 1, r))
  1786. X          err(SE_CONT, r);
  1787. X        b = 0;
  1788. X      }
  1789. X      else if (strcmp(l, "end") == 0)
  1790. X      {
  1791. X        /* check crc, close output file */
  1792. X        if (c == NULL)
  1793. X          err(SE_FORM, h);
  1794. X        if (c->n != 4 || c->b != ~c->c)
  1795. X          err(SE_CRC, r);
  1796. X        if (ferror(c->f) || fclose(c->f))
  1797. X          err(SE_FULL, r);
  1798. X        if (noisy)
  1799. X          fprintf(stderr, "%s received\n", r);
  1800. X        z = 0;
  1801. X        free((voidp *)c);
  1802. X        c = NULL;
  1803. X        b = 2;
  1804. X      }
  1805. X      else
  1806. X      {
  1807. X        for (q = l; *q && *q != ' '; q++)
  1808. X          ;
  1809. X        *q = 0;
  1810. X        fprintf(stderr, "%s: unsupported keyword '%s' ignored\n", warname, l);
  1811. X        b = 4;
  1812. X      }
  1813. X      break;
  1814. X    }
  1815. X  }
  1816. X}
  1817. X
  1818. X
  1819. void help()
  1820. X{
  1821. X  int i;
  1822. X  static char *text[] = {
  1823. X"Usage:",
  1824. X"   ship [-f] [-q] [-nnn] [-m address] [-s subject] files...",
  1825. X"",
  1826. X"   ships the files to stdout.  -m sends the output via the mailer to",
  1827. X"   address.  -nnn splits the output into pieces of nnnK bytes or less.",
  1828. X"   if -nnn is used without -m, the output goes to the files partxxxx,",
  1829. X"   where xxxx is 0001, 0002, etc.  If -0 is specified, the output goes",
  1830. X"   entirely to the file part0001.  -f uses a fast method with slightly",
  1831. X"   less performance.  If no files are given, stdin is used.  The special",
  1832. X"   filename '-' also takes input from stdin.  Files shipped from stdin",
  1833. X"   are unshipped to stdout.  This can be used to document a shipment.",
  1834. X"   When mailing, -s gives a subject line prefix.  -q inhibits messages.",
  1835. X"",
  1836. X"   ship -u [-o] [-q] files...",
  1837. X"   unship  [-o] [-q] files...",
  1838. X"",
  1839. X"   extracts the contents of the mail messages in files...  -o allows",
  1840. X"   existing files to be overwritten.  -u is implied if the name of the",
  1841. X"   executable is unship.  If no files are given, the input is from",
  1842. X"   stdin.  If any of the files were shipped from stdin, then they are",
  1843. X"   extracted to stdout."
  1844. X  };
  1845. X
  1846. X  puts(SHIPVER);
  1847. X  for (i = 0; i < sizeof(text)/sizeof(char *); i++)
  1848. X  {
  1849. X    printf(text[i]);
  1850. X    putchar('\n');
  1851. X  }
  1852. X  exit(0);
  1853. X}
  1854. X
  1855. X
  1856. void main(argc, argv)
  1857. int argc;               /* number of arguments */
  1858. char **argv;            /* table of argument strings */
  1859. X{
  1860. X  FILE *f;              /* input file */
  1861. X  char *p;              /* temporary variable */
  1862. X  int o;                /* overwrite flag */
  1863. X  int r;                /* temporary variable */
  1864. X  int s;                /* true if no names given */
  1865. X
  1866. X  /* No temporary file yet (for err()) */
  1867. X  *mname = 0;
  1868. X
  1869. X  /* No subject prefix yet */
  1870. X  *mprefix = 0;
  1871. X
  1872. X  /* See if help requested */
  1873. X  if (argc > 1 && (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "-?") == 0))
  1874. X    help();
  1875. X
  1876. X  /* Unship */
  1877. X  if ((p = strrchr(argv[0], PATHCUT)) == NULL)
  1878. X    p = argv[0];
  1879. X  else
  1880. X    p++;
  1881. X  r = 0;                                /* (make some compilers happier) */
  1882. X  if ((r = strncmp(p, "unship", 6)) == 0 ||
  1883. X      (r = strncmp(p, "UNSHIP", 6)) == 0 ||
  1884. X      (argc > 1 && strcmp(argv[1], "-u") == 0))
  1885. X  {
  1886. X    errname = "unship error";
  1887. X    warname = "unship warning";
  1888. X    r = r ? 2 : 1;                      /* next arg */
  1889. X    o = 0;                              /* disallow overwriting */
  1890. X    if (r < argc && strcmp(argv[r], "-o") == 0)
  1891. X    {
  1892. X      r++;
  1893. X      o = 1;                            /* allow overwriting */
  1894. X    }
  1895. X    if (r < argc && strcmp(argv[r], "-q") == 0)
  1896. X    {
  1897. X      r++;
  1898. X      noisy = 0;                        /* inhibit messages */
  1899. X    }
  1900. X    if (r < argc)
  1901. X      unship(argv + r, argc - r, o);    /* unship files in args */
  1902. X    else
  1903. X    {
  1904. X      char *a[1];       /* short list of names (one) */
  1905. X
  1906. X      a[0] = "-";
  1907. X      unship(a, 1, o);                  /* no args--do stdin */
  1908. X    }
  1909. X  }
  1910. X
  1911. X  /* Ship */
  1912. X  else
  1913. X  {
  1914. X    mail = 0;                           /* not mailing */
  1915. X    fast = 0;                           /* use base 85 encoding */
  1916. X    s = 1;                              /* no names given yet */
  1917. X    strcpy(sname, "-");                 /* output to stdout */
  1918. X    sfile = stdout;
  1919. X    slns = slmax = 0;
  1920. X    for (r = 1; r < argc; r++)          /* go through args */
  1921. X      if (argv[r][0] == '-')            /* option or stdin */
  1922. X        if (argv[r][1])                 /* option */
  1923. X        {
  1924. X          if (argv[r][1] == 'm')        /* mail output */
  1925. X          {
  1926. X            mail = 1;
  1927. X            mdest = NULL;               /* next arg is mail address */
  1928. X          }
  1929. X          else if (argv[r][1] == 's')   /* next arg is subject prefix */
  1930. X            mprefix = NULL;
  1931. X          else if (argv[r][1] == 'f')   /* fast arithmetic encoding */
  1932. X            fast = 1;
  1933. X          else if (argv[r][1] == 'q')   /* quiet operation */
  1934. X            noisy = 0;
  1935. X          else                          /* option is number of lines */
  1936. X          {
  1937. X            /* Check numeric option */
  1938. X            for (p = argv[r] + 1; *p; p++)
  1939. X              if (*p < '0' || *p > '9')
  1940. X                break;
  1941. X            if (*p || slmax)
  1942. X              err(SE_ARG, argv[r]);
  1943. X  
  1944. X            /* Zero means infinity, else convert */
  1945. X            if ((slmax = atol(argv[r] + 1)) == 0)
  1946. X              slmax = -1L;
  1947. X            else
  1948. X            {
  1949. X              long b;
  1950. X
  1951. X              b = slmax * 1000L;
  1952. X              slmax = (int)(b / (fast ? 81 : 77));
  1953. X              /* Note: five of the lines aren't that long, but that
  1954. X                 leaves some slack for mail headers, etc.  Also, note
  1955. X                 that we conservatively assume 1000 bytes/K and two
  1956. X                 bytes per new line. */
  1957. X            }
  1958. X          }
  1959. X        }
  1960. X        else                            /* input file is stdin */
  1961. X        {
  1962. X          if (mail && mdest == NULL)
  1963. X            err(SE_ARG, "- (no mail destination given)");
  1964. X          s = 0;
  1965. X          if (mail && !*mprefix)
  1966. X            strcpy(mprefix, "(stdin)");
  1967. X          ship("-", stdin);
  1968. X        }
  1969. X      else                              /* not option or stdin */
  1970. X        if (mail && mdest == NULL)      /* arg is mail address */
  1971. X          mdest = argv[r];
  1972. X        else if (mprefix == NULL)       /* arg is subject prefix */
  1973. X          mprefix = argv[r];
  1974. X        else                            /* arg is file to ship */
  1975. X        {
  1976. X          s = 0;
  1977. X          if ((f = fopen(argv[r], "r")) == NULL)
  1978. X            err(SE_FIND, argv[r]);
  1979. X          if (mail && !*mprefix)
  1980. X          {
  1981. X            int i;
  1982. X
  1983. X            for (i = 0, p = nopath(argv[r]); i < 8 && *p; p++)
  1984. X              if ((*p >= '0' && *p <= '9') || (*p >= 'A' && *p <= 'Z') ||
  1985. X                  (*p >= 'a' && *p <= 'z') || *p == '.' || *p == '_')
  1986. X                mprefix[i++] = *p;
  1987. X            mprefix[i] = 0;
  1988. X          }
  1989. X          ship(argv[r], f);
  1990. X          fclose(f);
  1991. X        }
  1992. X    if (s)                              /* no names--act as filter */
  1993. X      if (mail && mdest == NULL)
  1994. X        err(SE_ARG, "-m (no mail destination given)");
  1995. X      else if (mprefix == NULL)
  1996. X        err(SE_ARG, "-s (no subject prefix given)");
  1997. X      else
  1998. X      {
  1999. X        if (mail && !*mprefix)
  2000. X          strcpy(mprefix, "(stdin)");
  2001. X        ship("-", stdin);
  2002. X      }
  2003. X    endship(1);                         /* clean up */
  2004. X    if (noisy && (mail || slmax))
  2005. X      fprintf(stderr, "file%s%s %s\n",
  2006. X              strcmp("part0001", sname) ? "s part0001.." : " ", sname,
  2007. X              mail ? "mailed" : "written");
  2008. X  }
  2009. X
  2010. X  /* Done */
  2011. X  exit(0);
  2012. X}
  2013. END_OF_FILE
  2014. if test 38393 -ne `wc -c <'ship.c'`; then
  2015.     echo shar: \"'ship.c'\" unpacked with wrong size!
  2016. fi
  2017. # end of 'ship.c'
  2018. fi
  2019. echo shar: End of archive 5 \(of 7\).
  2020. cp /dev/null ark5isdone
  2021. MISSING=""
  2022. for I in 1 2 3 4 5 6 7 ; do
  2023.     if test ! -f ark${I}isdone ; then
  2024.     MISSING="${MISSING} ${I}"
  2025.     fi
  2026. done
  2027. if test "${MISSING}" = "" ; then
  2028.     echo You have unpacked all 7 archives.
  2029.     rm -f ark[1-9]isdone
  2030. else
  2031.     echo You still need to unpack the following archives:
  2032.     echo "        " ${MISSING}
  2033. fi
  2034. ##  End of shell archive.
  2035. exit 0
  2036.